home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / timer / sun4c.md / timerSun4c.c < prev    next >
C/C++ Source or Header  |  1990-11-09  |  10KB  |  403 lines

  1. /* 
  2.  * timerSun4c.c --
  3.  *
  4.  *    This file contains the routines that control the time of day clock 
  5.  *    and interrupt timers on the sun4c (SparcStation 1) machine. The
  6.  *    sun4c contains a Mostek MK48T12-15 chip for time of day and 
  7.  *    two interrupt timers.  
  8.  *
  9.  *    Until we get the data sheets for the Mostek chip, we use the interrupt
  10.  *    counters for both interupts and TOD.
  11.  *
  12.  * Copyright 1989 Regents of the University of California
  13.  * Permission to use, copy, modify, and distribute this
  14.  * software and its documentation for any purpose and without
  15.  * fee is hereby granted, provided that the above copyright
  16.  * notice appear in all copies.  The University of California
  17.  * makes no representations about the suitability of this
  18.  * software for any purpose.  It is provided "as is" without
  19.  * express or implied warranty.
  20.  */
  21.  
  22. #ifndef lint
  23. static char rcsid[] = "$Header: /sprite/src/kernel/timer/sun4c.md/RCS/timerSun4c.c,v 1.9 90/11/08 21:02:41 rab Exp $ SPRITE (Berkeley)";
  24. #endif /* not lint */
  25.  
  26. #include "sprite.h"
  27. #include "sys.h"
  28. #include "timer.h"
  29. #include "timerInt.h"
  30. #include "timerTick.h"
  31. #include "spriteTime.h"
  32. #include "mach.h"
  33. #include "prof.h"
  34. #include "devAddrs.h"
  35.  
  36. #include "timerMK48T12Int.h"
  37.  
  38. /*
  39.  * The sun4c contains two counters that count up to value in the limit 
  40.  * register and interrupt. The counters are defined by the following 
  41.  * structure. (Campus-1 Programmer's Model Version 7.5 page 11).
  42.  * We assign counter0 to be the call back interrupt timer and 
  43.  * counter1 to be the profile interrupt timer. Each counter and limit
  44.  * register is of the form:
  45.  *    struct {
  46.  *       int    limitReached :1; -- 1 if counter reached limit. 
  47.  *       int  value         :21; -- Value updated every microsecond. 
  48.  *       int  zeros         :10; -- Read as zero. 
  49.  *     }
  50.  */
  51.  
  52. typedef struct {
  53.     unsigned int callBackCounter; /* Call back counter */
  54.     unsigned int callBackLimit;   /* Limit register for call back counter. */
  55.     unsigned int profileCounter;  /* Profile counter. */
  56.     unsigned int profileLimit;    /* Limit register for profile counter. */
  57. } Counters;
  58.  
  59. /*
  60.  * COUNTER_SHIFT    - Number of bits to shift microsecond value for
  61.  *              counter. 
  62.  * COUNTER_LIMIT_REACH  - Bit signifying count has reached limit.
  63.  */
  64. #define    COUNTER_SHIFT 10
  65. #define    COUNTER_LIMIT_REACH 0x80000000
  66.  
  67. static volatile Counters *counterPtr = (volatile Counters *) DEV_COUNTER_ADDR;
  68.  
  69. /*
  70.  * The "free running counter"
  71.  */
  72. static Timer_Ticks todCounter;
  73.  
  74. int Timer_TimerServiceInterrupt();
  75.  
  76. /*
  77.  * Timer interval as a Time value. This is the period between callbacks.
  78.  */
  79.  
  80. static Time time = { 0, TIMER_CALLBACK_INTERVAL_APPROX};
  81.  
  82.  
  83. /* 
  84.  *----------------------------------------------------------------------
  85.  *
  86.  * Timer_TimerInit --
  87.  *
  88.  *    Initialize the periodic timer. Since there is no way to turn off
  89.  *    the counters will wait and do all the work in Timer_TimerStart().
  90.  *
  91.  *
  92.  * Results:
  93.  *    None.
  94.  *
  95.  * Side effects:
  96.  *    The timer is initialized.
  97.  *
  98.  *----------------------------------------------------------------------
  99.  */
  100. /*ARGSUSED*/
  101. void
  102. Timer_TimerInit(timer)
  103.     unsigned short     timer;
  104.      if (timer == TIMER_CALLBACK_TIMER) {
  105.      Mach_SetHandler(10, Timer_TimerServiceInterrupt, (ClientData) timer); 
  106.      } else if (timer == TIMER_PROFILE_TIMER) {
  107.      Mach_SetHandler(14, Timer_TimerServiceInterrupt, (ClientData) timer); 
  108.      } else {
  109.     panic("Timer_TimerInit: unknown timer %d\n", timer);
  110.      }
  111. }
  112.  
  113.  
  114. /*
  115.  *----------------------------------------------------------------------
  116.  *
  117.  * Timer_TimerStart --
  118.  *
  119.  *    Loads the specified timer with a new value to count from
  120.  *    and starts the timer.
  121.  *
  122.  *    N.B. The timer must have been initialized with Timer_TimerInit
  123.  *    before this routine is called.
  124.  *
  125.  * Results:
  126.  *    None.
  127.  *
  128.  * Side effects:
  129.  *    The timer starts ticking.
  130.  *
  131.  *----------------------------------------------------------------------
  132.  */
  133.  
  134. void
  135. Timer_TimerStart(timer)
  136.     register unsigned short timer;
  137. {
  138.     unsigned int junk;
  139.  
  140.     /*
  141.      * To start the timer we load the limit register with the correct 
  142.      * count and clear any pending interrupt. 
  143.      */
  144.      if (timer == TIMER_CALLBACK_TIMER) {
  145.      counterPtr->callBackLimit =
  146.              ((TIMER_CALLBACK_INTERVAL_APPROX) << COUNTER_SHIFT);
  147.      junk = counterPtr->callBackLimit;
  148.       DISABLE_INTR();
  149.      *Mach_InterruptReg |= MACH_ENABLE_COUNTER0_INTR_LEVEL;
  150.      ENABLE_INTR();
  151.  
  152.      } else if (timer == TIMER_PROFILE_TIMER) {
  153.      counterPtr->profileLimit =
  154.              ((TIMER_PROFILE_INTERVAL_APPROX) << COUNTER_SHIFT);
  155.      junk = counterPtr->profileLimit;
  156.          DISABLE_INTR();
  157.      *Mach_InterruptReg |= MACH_ENABLE_COUNTER1_INTR_LEVEL;
  158.      ENABLE_INTR();
  159.      } else {
  160.     panic("Timer_TimerInit: unknown timer %d\n", timer);
  161.      }
  162. #ifdef lint
  163.     junk = junk;
  164. #endif
  165.  
  166.  
  167. }
  168.  
  169.  
  170.  
  171. /*
  172.  *----------------------------------------------------------------------
  173.  *
  174.  * Timer_TimerInactivate --
  175.  *
  176.  *    Stops the timer so that it will not cause interrupts.
  177.  *
  178.  * Results:
  179.  *    None.
  180.  *
  181.  * Side effects:
  182.  *    The timer is stopped.
  183.  *
  184.  *----------------------------------------------------------------------
  185.  */
  186.  
  187. void
  188. Timer_TimerInactivate(timer)
  189.     register unsigned short timer;
  190. {
  191.     if (timer == TIMER_CALLBACK_TIMER) {
  192.     /*
  193.      * As long as we use the callback timer to keep track of time
  194.      * we shouldn't turn it off.
  195.      */
  196. #ifdef notdef
  197.      DISABLE_INTR();
  198.      *Mach_InterruptReg &= ~MACH_ENABLE_COUNTER0_INTR_LEVEL;
  199.      ENABLE_INTR();
  200. #endif
  201.     } else if (timer == TIMER_PROFILE_TIMER) {
  202.      DISABLE_INTR();
  203.      *Mach_InterruptReg &= ~MACH_ENABLE_COUNTER1_INTR_LEVEL;
  204.      ENABLE_INTR();
  205.     } else {
  206.     panic("Timer_TimerInactivate: unknown timer %d\n", timer);
  207.     }
  208.  
  209. }
  210.  
  211. /*
  212.  *----------------------------------------------------------------------
  213.  *
  214.  *  Timer_TimerServiceInterrupt --
  215.  *
  216.  *      This routine is called at every timer interrupt. 
  217.  *      It calls the timer callback queue handling if the callback timer 
  218.  *    expired and calls the profiling interrupt handling if the 
  219.  *    profile callback timer expired.
  220.  *
  221.  *  Results:
  222.  *    None.
  223.  *
  224.  *  Side Effects:
  225.  *    Routines on the timer queue may cause side effects. Profile
  226.  *    collect may take place. 
  227.  *    
  228.  *
  229.  *----------------------------------------------------------------------
  230.  */
  231.  
  232. int
  233. Timer_TimerServiceInterrupt(clientData, pc)
  234.     ClientData    clientData;            /* Really Counter number */
  235.     unsigned int    pc;        /* Only for sun4 version. */
  236.     register unsigned int junk;
  237.  
  238.     if ((unsigned int) clientData == TIMER_PROFILE_TIMER) {
  239.     /*
  240.      * Clear interrupt by reading limit register. 
  241.      */
  242.     junk = counterPtr->profileLimit;
  243.     TIMER_PROFILE_ROUTINE(pc);
  244. #       ifdef GATHER_STAT
  245.         timer_Statistics.profile++;
  246. #       endif
  247.     } else  if ((unsigned int) clientData == TIMER_CALLBACK_TIMER) {
  248.     /*
  249.      * Clear interrupt by reading limit register. 
  250.      */
  251.     junk = counterPtr->callBackLimit;
  252. #ifndef TOD_WORKING
  253.     /*
  254.      * Until we get the TOD chip working. Use the callback counter
  255.      * to keep track on time of day.
  256.      */
  257.      todCounter.microseconds += TIMER_CALLBACK_INTERVAL_APPROX;
  258.      if (todCounter.microseconds > ONE_SECOND) {
  259.          todCounter.seconds++;
  260.          todCounter.microseconds -= ONE_SECOND;
  261.      }
  262. #endif
  263.     if (mach_KernelMode == 0) {
  264.         Proc_GetCurrentProc()->Prof_PC = pc;
  265.     }
  266.         TIMER_CALLBACK_ROUTINE(TIMER_CALLBACK_INTERVAL_APPROX, time);
  267.     } else {
  268.     panic("Timer_TimerServiceInterrupt: Unknown timer %d\n", 
  269.             (int) clientData);
  270.     }
  271. #ifdef lint
  272.     junk = junk;
  273. #endif
  274.     return 0;
  275. }
  276.  
  277. /*
  278.  *----------------------------------------------------------------------
  279.  *
  280.  * Timer_CounterInit --
  281.  *
  282.  *    Initializes the chip's free-running counters. Until we get the
  283.  *    TOD chip just use a counter updated by the CALL BACK interrupt
  284.  *    handler.
  285.  *
  286.  *    
  287.  * Results:
  288.  *    None.
  289.  *
  290.  * Side effects:
  291.  *    None.
  292.  *
  293.  *----------------------------------------------------------------------
  294.  */
  295.  
  296. void
  297. Timer_CounterInit()
  298. {
  299.     todCounter.seconds = 0;
  300.     todCounter.microseconds = 0;
  301. }
  302.  
  303. /* 
  304.  *----------------------------------------------------------------------
  305.  *
  306.  *  Timer_GetCurrentTicks --
  307.  *
  308.  *      Return microseconds since boot.
  309.  *
  310.  *  Results:
  311.  *    The system up-time in ticks.
  312.  *
  313.  *  Side effects:
  314.  *    None.
  315.  *
  316.  *----------------------------------------------------------------------
  317.  */
  318. void
  319. Timer_GetCurrentTicks(ticksPtr)
  320.     Timer_Ticks    *ticksPtr;    /* Buffer to place current time. */
  321. {
  322.     DISABLE_INTR();
  323.  
  324.     *ticksPtr = todCounter;
  325.  
  326.     ENABLE_INTR();
  327. }
  328.  
  329. /* 
  330.  *----------------------------------------------------------------------
  331.  *
  332.  *  Timer_GetInfo --
  333.  *
  334.  *      Dummy routine to dump timer state.
  335.  *
  336.  *  Results:
  337.  *    None.
  338.  *
  339.  *  Side effects:
  340.  *    None.
  341.  *
  342.  *----------------------------------------------------------------------
  343.  */
  344. /*ARGSUSED*/
  345. void
  346. Timer_TimerGetInfo(data)
  347.     ClientData    data;    /* Not used. */
  348. {
  349. }
  350.  
  351. /*
  352.  *----------------------------------------------------------------------
  353.  *
  354.  * TimerHardwareUniversalTimeInit --
  355.  *
  356.  *     Not implemented yet.
  357.  *
  358.  * Results:
  359.  *    None.
  360.  *
  361.  * Side effects:
  362.  *    None.
  363.  *
  364.  *----------------------------------------------------------------------
  365.  */
  366.  
  367. /*ARGSUSED*/
  368. void
  369. TimerHardwareUniversalTimeInit(timePtr, localOffsetPtr, DSTPtr)
  370.     Time *timePtr;        /* Buffer to hold universal time. */
  371.     int  *localOffsetPtr;    /* Buffer to hold local offset. */
  372.     Boolean *DSTPtr;        /* Buffer to hold DST allowed flag. */
  373. {
  374. }
  375.  
  376. /*
  377.  *----------------------------------------------------------------------
  378.  *
  379.  * TimerSetHardwareUniversalTime --
  380.  *
  381.  *    Not implemented yet.
  382.  *
  383.  * Results:
  384.  *    None.
  385.  *
  386.  * Side effects:
  387.  *    None.
  388.  *
  389.  *----------------------------------------------------------------------
  390.  */
  391.  
  392. /*ARGSUSED*/
  393. void
  394. TimerSetHardwareUniversalTime(timePtr, localOffset, DST)
  395.     Time *timePtr;        /* universal time. */
  396.     int  localOffset;        /* local offset. */
  397.     Boolean DST;        /* DST allowed flag. */
  398. {
  399. }
  400.  
  401.